Refactor: Block Editor#35257
Conversation
…figuration and setup
❌ Issue Linking RequiredThis PR could not be linked to an issue. All PRs must be linked to an issue for tracking purposes. How to fix this:Option 1: Add keyword to PR body (Recommended - auto-removes this comment)
Why is this required?Issue linking ensures proper tracking, documentation, and helps maintain project history. It connects your code changes to the problem they solve.--- This comment was automatically generated by the issue linking workflow |
|
Claude finished @rjvelazco's task in 5m 2s —— View job PR Review — Block Editor Refactor (synchronize re-review)
Resolved since prior review
Still unresolved from prior review
New issues since prior review
Other observations (no change requested)
RecommendationMerge-blocking: N1 (env-var string-flag bug in
|
|
Rollback Safety Analysis - Safe to Roll Back. All 9 changed files are frontend Angular config only (new-block-editor library scaffold). Label AI: Safe To Rollback applied. |
… the new Block Editor V1
…older enhancements
…d error handling and empty state management
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Autofix is kicking off a free cloud agent to fix these issues. This run is complimentary, but you can enable autofix for all future PRs in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 77fd1d1. Configure here.
…o dialogs, enhancing search and display functionality
|
You have used all of your free Bugbot PR reviews. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
|
Rollback Safety Analysis - Safe to Roll Back. All 57 changed files are frontend Angular/TypeScript only (new-block-editor library scaffold, block-editor app refactor, SCSS, package.json). No database migrations, Elasticsearch mapping changes, API contract changes, or any backend code modified. Label AI: Safe To Rollback applied. |
…ity and image properties form
…gle grid extension and enhance resizing capabilities
Legal RiskThe following dependencies were released under a license that RecommendationWhile merging is not directly blocked, it's best to pause and consider what it means to use this license before continuing. If you are unsure, reach out to your security team or Semgrep admin to address this issue. GPL-2.0 MPL-2.0 |
…proved store management, and updated slash menu functionality - Added a comprehensive porting checklist for tracking features in the new block editor. - Introduced EditorStore for managing editor state, including allowed block types and language ID. - Updated slash menu service to utilize the new store for block type filtering. - Refactored image and video extensions to use consistent node names. - Improved editor component with additional input properties for better integration with dotCMS content types. - Cleaned up unused code and comments in editor click handling. This commit enhances the overall functionality and maintainability of the new block editor.
zJaaal
left a comment
There was a problem hiding this comment.
This is behind a FF so we can iterate over with no issues
…se-insensitive string comparisons
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Components were switched to getFeatureFlagWithDefault for explicit NOT_FOUND defaulting, but the specs still mocked only the legacy getFeatureFlag. toSignal(undefined) crashed in the constructor — surfaced in CI as a misleading "HTMLCanvasElement.getContext" warning. Adds the missing method to all four affected mocks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ServiceMock Same regression as the previous fix, different surface. The shared `dotPropertiesServiceMock` in `libs/portlets/edit-ema/portlet/src/lib/shared/mocks.ts` is consumed by `edit-ema-editor.component.spec`, `dot-ema-shell.component.spec`, and `dot-uve.store.integration.spec`. None of them stub `getFeatureFlagWithDefault`, so the editor's transitive child DotBlockEditorSidebarComponent crashed in its constructor with `toSignal(undefined)`. Adds the method (plus `getFeatureFlag` for consistency) to the shared mock; covers all three callers in one place. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>


🎯 What's this PR about?
This PR introduces a completely refactored Block Editor built on top of TipTap v3 with a modern Angular standalone architecture. The goal: make the editor faster, easier to maintain, and easier to extend — while keeping the existing user experience and content format intact.
Videos
video.mov
video.mov
feature-flag.mov
✨ Features
Everything users love about the Block Editor — now rebuilt with a cleaner foundation:
/) — quickly insert blocks, content types, and contentlets without leaving the keyboard🚦 Rollout & rollback safety — feature flag
The new editor ships behind a feature flag so existing customer instances cannot be broken by an unexpected regression. Both editors are bundled together for this transition window; the JSP that renders the field picks which custom element to mount based on the flag.
FEATURE_FLAG_NEW_BLOCK_EDITOR(follows the standardFEATURE_FLAG_*prefix convention)false→ the legacy editor renders for every customer until they explicitly opt indotmarketing-config.properties— defaultfalseFeatureFlagName.java— Java constantConfigurationResource.java— exposed to the frontend via the config endpoint whitelistFeaturedFlagsenum in@dotcms/dotcms-models— referenced by the three Angular consumers (dot-edit-content-block-editor,dot-block-editor-sidebar,dot-content-compare-block-editor)edit_field.jsp—ConfigUtils.isFeatureFlagOn("FEATURE_FLAG_NEW_BLOCK_EDITOR")selects between<dotcms-block-editor>(new) and<dotcms-old-block-editor>(legacy)FEATURE_FLAG_NEW_BLOCK_EDITOR=truein the dotCMS config or set it via the admin properties UI. No restart required.core-web/libs/new-block-editor/CLEANUP_FEATURE_FLAG.md— step-by-step instructions for removing the flag, deleting the legacy lib, renamingnew-block-editor→block-editor, and droppingtippy.jsonce QA signs off.🔄 Backwards compatibility
allowedBlocksandallowedContentTypesfield variables behave exactly like before.<dotcms-block-editor>web component keeps the same inputs/outputs/JSON shape. The field-rendering JSP picks between<dotcms-block-editor>(new) and<dotcms-old-block-editor>(legacy) based on the feature flag, so the customer-facing field stays the same regardless of which editor renders.dot-edit-content-block-editor), EMA (dot-block-editor-sidebar), and Content Compare (dot-content-compare-block-editor) each gained a small flag-driven@if/@elsethat mounts the new or legacy editor. Public inputs/outputs of those portlet components are unchanged. The shim is removed by the cleanup runbook once QA signs off.🛠 Changes
Apps
apps/dotcms-block-editor— migrated fromNgModulebootstrap to Angular standalone (bootstrapApplication). Registers the new<dotcms-block-editor>custom element from@dotcms/new-block-editor, and also registers the legacy<dotcms-old-block-editor>custom element (from the preserved@dotcms/block-editorlib) so the field-rendering JSP can swap between the two via the feature flag. The legacy registration block is removed by the cleanup runbook once QA signs off.Libraries
libs/new-block-editor— brand new library that hosts the refactored editor, its extensions, services, and UI.libs/block-editor— kept on this branch as the rollback target. No new feature work goes here; it's marked@deprecatedand slated for deletion in the cleanup PR.Dependencies
ngx-tiptapupgraded to latest majors@tiptap/extension-code-block-lowlightfor code-block syntax highlighting (paired with a custom Angular node view that renders a PrimeNG language picker)Styling
styles.csscodeblockReuses existing data-access services
The new editor does not duplicate HTTP plumbing. It consumes services already in
@dotcms/data-access:DotContentTypeService,DotContentSearchService— slash menu content pickersDotAiService— AI content & image generationDotUploadFileService— temp upload + workflow PUBLISHDotLanguagesService,DotMessageService— language metadata & i18nEditor-specific concerns (state, popovers, modals, slash menu orchestration, contentlet-edit URL caching) live as small local services inside the lib.
🏗 New project structure
Architectural rule of thumb:
🧪 How to verify
/→ confirm the slash menu opens, lists allowed blocks, and the content-type sub-picker loads contentlets.FEATURE_FLAG_NEW_BLOCK_EDITOR=trueand reload — the new<dotcms-block-editor>element should mount instead of<dotcms-old-block-editor>. Toggle back tofalseand confirm the legacy editor renders again with the same content intact.Note
High Risk
High risk because this is a large refactor that swaps the block editor app to a new standalone editor implementation, upgrades TipTap/ngx-tiptap major versions, and adds dotCMS upload/search integrations including a hardcoded auth token/base URL in code.
Overview
Replaces the
dotcms-block-editorapp's NgModule-based bootstrap with Angular standalonebootstrapApplicationand points the app at the newEditorComponentexported from@dotcms/new-block-editor, alongside updated Angular build target config (new executor/outputPath structure, dev config, baseHref).Adds a new
new-block-editorlibrary implementing an experimental TipTap v3-based editor with slash menu, toolbar, drag-handle gutter, link/image/video/table dialogs, emoji picker, upload placeholders, and dotCMS-backed asset/content-type search + upload services.Updates global styling for the new editor UI (Tailwind layers, typography plugin, Material Symbols, TipTap/table/link/upload-placeholder styles) and bumps editor-related dependencies (TipTap v3,
ngx-tiptap, Floating UI, emoji-mart); also removes a shared SCSScodestyle block.Reviewed by Cursor Bugbot for commit 77fd1d1. Bugbot is set up for automated code reviews on this repo. Configure here.